package controllers;

import java.net.HttpURLConnection;
import java.net.URL;
import java.text.DecimalFormat;
import java.util.ArrayList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import com.google.gson.Gson;

import direction.*;
import direction.Sequence.SequenceType;
import model.Stop;
import play.*;
import play.mvc.*;


public class Application extends Controller {
	private static final String LICENSE_KEY="AgQ1opM21OC4EObtlwHbpg8aA7BQOMICg6jGfJiG9aJAJVPUen9CGGO5juIPGS2x";

  public static Result findBusService(String jsoncallback,String busService) {
	    Gson gson = new Gson();
		/* System.out.println(Stop.find.byId("E01820").stop_name);
		  System.out.println();*/
		//  model.Route r = new model.Route();
		// List<model.Route> routes=model.Route.getStops(busservice);
		  //for(model.Route r:routes)
	  ArrayList<Stop> stops =model.Route.getStops(busService);
	  ArrayList<String> stopNames=new ArrayList<String>();

	  for(Stop s:stops){
		stopNames.add(s.stop_name);
	  }
    return ok(jsoncallback+"("+gson.toJson(stopNames)+")");
  }
  
  

  public static Result RoutingImage(String address1, String address2, String date, String time){
	 
		
		// bing map datetime: 03/01/2011 05:42:00

		String dateTime= date+ " " + time;

		String routingImageURL="dev.virtualearth.net/REST/v1/Imagery/Map/Road/Routes/Transit?waypoint.0="+address1+" ,Pittsburgh"+"&waypoint.1="+address2+" ,Pittsburgh"+"&timeType=Departure&dateTime="+dateTime+"&zoomLevel=10&mapSize=400,400&key="+LICENSE_KEY;
	  
		return ok(routingImageURL);
  }
  
  public static Result TransitRoute(String jsoncallback,String address1, String address2, String date, String time){
	    Gson gson = new Gson();

	    String output="";
	    String jsonCallbackParam =jsoncallback;
	     
		try{


			
			// bing map datetime: 03/01/2011 05:42:00
			String dateTime= date+ " " + time;

		    
		    String routeRestUrl="http://dev.virtualearth.net/REST/V1/Routes/Transit?du=mi&wp.0="+address1+", Pittsburgh&wp.1="+address2+", Pittsburgh&timeType=Departure&dateTime="+dateTime+"&output=xml&key="+LICENSE_KEY;
			System.out.println(routeRestUrl);
			

			
			URL hostURL = new URL(routeRestUrl.replaceAll(" ", "%20"));
					
			HttpURLConnection urlcon = (HttpURLConnection) hostURL.openConnection();
			urlcon.setRequestMethod("GET");
			urlcon.setDoOutput(true);
			urlcon.setDoInput(true);
			urlcon.setUseCaches(false);

			
			Route routeObj = new Route();
			
			
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			DocumentBuilder docBuild = factory.newDocumentBuilder();
			Document xmlResponse = docBuild.parse(urlcon.getInputStream());

			System.out.println(xmlResponse.getTextContent());

			if(xmlResponse == null){
				Fault fault = new Fault();
				fault.setFaultDescription("Failed to send request");
			   return ok(jsonCallbackParam+"("+gson.toJson(fault)+")");
			}
			else{
				boolean faultConditioner=false;
				try{
					Element docEle = xmlResponse.getDocumentElement();
					Element faultElement=(Element)docEle.getElementsByTagName("ErrorDetails").item(0);
					String faultString=getTextValue(faultElement,"string");
					Fault fault = new Fault();
					fault.setFaultDescription(faultString);
				    faultConditioner=true;
				    return ok(jsonCallbackParam+"("+gson.toJson(fault)+")");
				}
				catch(NullPointerException e){
				}

				if(faultConditioner==false){
					Element docEle = xmlResponse.getDocumentElement();
					
					Element routeElement=(Element)docEle.getElementsByTagName("Route").item(0);

					DecimalFormat twoDForm = new DecimalFormat("#.##");
					DecimalFormat dForm = new DecimalFormat("#");
					String distance=twoDForm.format(Double.parseDouble(getTextValue(routeElement,"TravelDistance")))+" Miles";
					String duration=Integer.parseInt(getTextValue(routeElement,"TravelDuration"))/60+" Mins "+Integer.parseInt(getTextValue(routeElement,"TravelDuration"))%60+" Secs";
					
					routeObj.setDistance(distance);
					routeObj.setDuration(duration);
					
					NodeList list = docEle.getElementsByTagName("ItineraryItem");
					if(list != null || list.getLength() != 0){
						for(int i=0; i<xmlResponse.getElementsByTagName("ItineraryItem").getLength(); i++){
							Element element = (Element)list.item(i);

							Sequence sequence = new Sequence();
					    	sequence.setSequenceId(i+1); 
							String instruction = element.getElementsByTagName("Instruction").item(0).getChildNodes().item(0).getNodeValue();
							sequence.setDescription(instruction);
							
							Element detailElement=(Element)element.getElementsByTagName("Detail").item(0);
							String action = getTextValue(detailElement,"ManeuverType");
							if(action.equals("Walk")){
								sequence.setSequenceType(SequenceType.Walk);
							}
							else if(action.equals("TakeTransit")){
								sequence.setSequenceType(SequenceType.TakeTransit);
								sequence.setBusNumber(getTextValue(element,"AbbreviatedName"));	
							}
							
							else if(action.equals("TransitDepart")){
								sequence.setSequenceType(SequenceType.Board);
								sequence.setBusStop(getTextValue(detailElement,"Name"));
								String busTiming =getTextValue(element,"Time");
								sequence.setBusTiming(busTiming.substring(busTiming.indexOf("T")+1,busTiming.length()-3));
							}
							
							else if(action.equals("TransitArrive")){
								sequence.setSequenceType(SequenceType.Alight);
								sequence.setBusStop(getTextValue(detailElement,"Name"));
							}
							
						   routeObj.addSequence(sequence);
	
					}
					
				}
					     
						
					    //output sucessful JSON
					    return ok(jsonCallbackParam+"("+gson.toJson(routeObj)+")");

					
				}
			}
		}
		catch(Exception e){
			e.printStackTrace();
			Fault fault = new Fault();
			fault.setFaultDescription("Failed to parse xml response");
		    return ok(jsonCallbackParam+"("+gson.toJson(fault)+")");
		}
		Fault fault = new Fault();
		fault.setFaultDescription("Failed to send request");
	   return ok(jsonCallbackParam+"("+gson.toJson(fault)+")");
	}
	
	private static String getTextValue(Element ele, String tagName) {
		String textVal = null;
		NodeList nl = ele.getElementsByTagName(tagName);
		if(nl != null && nl.getLength() > 0) {
			Element el = (Element)nl.item(0);
			textVal = el.getFirstChild().getNodeValue();
		}

		return textVal;
	}
  }